package icasue.base.config.filter;

import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.MethodMetadata;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2021/7/16 下午5:24
 * @UpdateDate:
 * @Description:
 */
public class OnElCondition extends FilterElCondition{

    /**
     * 方法继承于 SpringBootCondition, 这里做并非
     * @param context
     * @param metadata
     * @return
     */
    @Override
    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
        MergedAnnotations annotations = metadata.getAnnotations();
        if(annotations.isPresent(ElCondition.class)){
            MergedAnnotation<ElCondition> annotation = annotations.get(ElCondition.class);
            String componentTypeDesc = "Not available component desc";
            try {
                Object source = annotation.getSource();
                Field touch_component = null;
                try {
                    touch_component = source.getClass().getDeclaredField("name");
                }catch (Throwable e){
                    try {
                        touch_component = source.getClass().getDeclaredField("className");
                    }catch (Throwable e2){
                        touch_component = source.getClass().getDeclaredField("toStringValue");
                    }
                }
                touch_component.setAccessible(true);
                componentTypeDesc = touch_component.get(source).toString();
            }catch (Throwable e){
                /*Ignore type error.*/
            }
            List<String> elConditions = Arrays.asList(annotation.getStringArray("value"));
            Optional<Boolean> markFailed = super.doElValid(componentTypeDesc, elConditions);
            if(markFailed.isPresent() && markFailed.get().booleanValue()){
                ConditionMessage matchMessage = ConditionMessage.empty();
                if (metadata instanceof ClassMetadata) {
                    ClassMetadata classMetadata = (ClassMetadata) metadata;
                    matchMessage.append("class [" + classMetadata.getClassName() + "]")
                            .append(" register failed, reason :: el-expression check failed.");
                }else {
                    MethodMetadata methodMetadata = (MethodMetadata) metadata;
                    matchMessage.append("method [" + methodMetadata.getDeclaringClassName() + "#"
                            + methodMetadata.getMethodName() + "]").append(" register failed, reason :: el-expression check failed.");
                }
                return ConditionOutcome.noMatch(matchMessage);
            }
        }
        return ConditionOutcome.match();
    }
}
